package com.example.authsystem.controller;

import com.example.authsystem.dto.JwtResponse;
import com.example.authsystem.dto.LoginRequest;
import com.example.authsystem.dto.RegisterRequest;
import com.example.authsystem.entity.User;
import com.example.authsystem.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;

import java.util.Map;

@RestController
@RequestMapping("/api/auth")
@Tag(
        name = "用户认证管理",
        description = "提供用户注册、登录、令牌刷新等认证相关功能的API接口"
)
public class AuthController {

    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    private UserService userService;

    @GetMapping("/")
    public String home() {
        return "Auth System is running successfully!";
    }

    @PostMapping("/register")
    @Operation(
            summary = "用户注册",
            description = "创建新用户账户。系统将验证用户名和邮箱的唯一性，密码会进行安全加密处理后存储。"
    )
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "注册成功",
                    content = @Content(
                            mediaType = MediaType.TEXT_PLAIN_VALUE,
                            schema = @Schema(type = "string", example = "User registered successfully! User ID: 12345")
                    )
            ),
            @ApiResponse(
                    responseCode = "400",
                    description = "注册失败 - 参数验证错误或用户信息已存在",
                    content = @Content(
                            mediaType = MediaType.TEXT_PLAIN_VALUE,
                            schema = @Schema(type = "string"),
                            examples = {
                                    @ExampleObject(name = "邮箱已存在", value = "Email already exists"),
                                    @ExampleObject(name = "用户名已存在", value = "Username already exists"),
                                    @ExampleObject(name = "参数验证失败", value = "Password must be at least 6 characters long")
                            }
                    )
            )
    })
    public ResponseEntity<?> registerUser(
            @Parameter(
                    description = "用户注册信息",
                    required = true,
                    content = @Content(
                            schema = @Schema(implementation = RegisterRequest.class),
                            examples = @ExampleObject(
                                    name = "注册信息示例",
                                    description = "标准用户注册请求",
                                    value = """
                                            {
                                              "username": "john_smith",
                                              "email": "john.smith@example.com",
                                              "password": "mySecurePass123"
                                            }
                                            """
                            )
                    )
            )
            @Valid @RequestBody RegisterRequest registerRequest
    ) {
        logger.info("Register request received: username={}, email={}", registerRequest.getUsername(), registerRequest.getEmail());
        try {
            User user = userService.registerUser(registerRequest);
            return ResponseEntity.ok().body("User registered successfully! User ID: " + user.getId());
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PostMapping("/login")
    @Operation(
            summary = "用户登录",
            description = """
                    用户登录验证，支持用户名或邮箱方式登录。
                    成功登录后返回访问令牌(AccessToken)和刷新令牌(RefreshToken)。
                    可选择提供设备ID和位置信息用于安全审计和异常检测。
                    """
    )
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "登录成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = JwtResponse.class),
                            examples = @ExampleObject(
                                    name = "登录成功响应",
                                    description = "包含JWT令牌的完整响应",
                                    value = """
                                            {
                                              "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huX3NtaXRoIiwiaWF0IjoxNjE2MjM5MDIyLCJleHAiOjE2MTYyNDI2MjJ9.4qgpUOkz8HwFUiTKVG8K9YfauUt2-TbHcvn0x1z8Xss",
                                              "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huX3NtaXRoIiwiaWF0IjoxNjE2MjM5MDIyLCJleHAiOjE2MTYzMjU0MjJ9.8HwFUiTKVG8K9YfauUt2-TbHcvn0x1z8Xss4qgpUOkz",
                                              "tokenType": "Bearer",
                                              "expiresIn": 3600
                                            }
                                            """
                            )
                    )
            ),
            @ApiResponse(
                    responseCode = "400",
                    description = "登录失败 - 凭据无效或账户问题",
                    content = @Content(
                            mediaType = MediaType.TEXT_PLAIN_VALUE,
                            schema = @Schema(type = "string"),
                            examples = {
                                    @ExampleObject(name = "凭据错误", value = "Invalid username or password"),
                                    @ExampleObject(name = "用户不存在", value = "User not found"),
                                    @ExampleObject(name = "账户锁定", value = "Account has been locked due to multiple failed login attempts")
                            }
                    )
            )
    })
    public ResponseEntity<?> loginUser(
            @Parameter(
                    description = "用户登录凭据",
                    required = true,
                    content = @Content(
                            schema = @Schema(implementation = LoginRequest.class),
                            examples = @ExampleObject(
                                    name = "登录请求示例",
                                    description = "使用用户名和密码登录",
                                    value = """
                                            {
                                              "username": "john_smith",
                                              "password": "mySecurePass123"
                                            }
                                            """
                            )
                    )
            )
            @Valid @RequestBody LoginRequest loginRequest,

            @Parameter(
                    name = "Device-ID",
                    description = """
                            设备唯一标识符，用于：
                            - 设备管理和追踪
                            - 异常登录检测
                            - 安全审计记录
                            建议格式：设备类型-设备型号-唯一ID
                            """,
                    example = "iPhone-14-Pro-A1B2C3D4E5",
                    schema = @Schema(type = "string", maxLength = 100)
            )
            @RequestHeader(value = "Device-ID", required = false) String deviceId,

            @Parameter(
                    name = "Location",
                    description = """
                            用户登录的地理位置信息，用于：
                            - 异地登录检测和提醒
                            - 安全审计和风险评估
                            - 地域访问统计
                            建议格式：城市, 省份/州, 国家
                            """,
                    example = "深圳, 广东, 中国",
                    schema = @Schema(type = "string", maxLength = 200)
            )
            @RequestHeader(value = "Location", required = false) String location
    ) {
        try {
            deviceId = deviceId != null ? deviceId : "unknown";
            location = location != null ? location : "unknown";

            JwtResponse jwtResponse = userService.loginUser(loginRequest, deviceId, location);
            return ResponseEntity.ok(jwtResponse);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PostMapping("/refresh")
    @Operation(
            summary = "刷新访问令牌",
            description = """
                    使用有效的刷新令牌获取新的访问令牌，用于延长用户会话时间。
                    当访问令牌即将过期或已过期时，客户端应使用此接口获取新的访问令牌，
                    避免用户重新登录，提升用户体验。
                                
                    注意事项：
                    - 刷新令牌有更长的有效期（通常7-30天）
                    - 每次刷新后建议更新存储的令牌
                    - 刷新令牌被使用后可能会轮换（根据安全策略）
                    """
    )
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "令牌刷新成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = JwtResponse.class),
                            examples = @ExampleObject(
                                    name = "刷新成功响应",
                                    description = "返回新的访问令牌和原刷新令牌",
                                    value = """
                                            {
                                              "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huX3NtaXRoIiwiaWF0IjoxNjE2MjQyNjIyLCJleHAiOjE2MTYyNDYyMjJ9.newAccessToken_4qgpUOkz8HwFUiTKVG8K9YfauUt2",
                                              "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huX3NtaXRoIiwiaWF0IjoxNjE2MjM5MDIyLCJleHAiOjE2MTYzMjU0MjJ9.8HwFUiTKVG8K9YfauUt2-TbHcvn0x1z8Xss4qgpUOkz",
                                              "tokenType": "Bearer",
                                              "expiresIn": 3600
                                            }
                                            """
                            )
                    )
            ),
            @ApiResponse(
                    responseCode = "400",
                    description = "令牌刷新失败 - 刷新令牌无效或已过期",
                    content = @Content(
                            mediaType = MediaType.TEXT_PLAIN_VALUE,
                            schema = @Schema(type = "string"),
                            examples = {
                                    @ExampleObject(name = "令牌无效", value = "Invalid refresh token"),
                                    @ExampleObject(name = "令牌过期", value = "Refresh token has expired"),
                                    @ExampleObject(name = "令牌格式错误", value = "Malformed refresh token"),
                                    @ExampleObject(name = "用户不存在", value = "User associated with refresh token not found")
                            }
                    )
            )
    })
    public ResponseEntity<?> refreshToken(
            @Parameter(
                    description = """
                            包含刷新令牌的请求体。
                            必须包含 'refreshToken' 字段，其值为有效的JWT刷新令牌。
                            """,
                    required = true,
                    content = @Content(
                            schema = @Schema(
                                    type = "object",
                                    description = "刷新令牌请求对象",
                                    example = """
                                            {
                                              "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                                            }
                                            """
                            ),
                            examples = @ExampleObject(
                                    name = "刷新令牌请求",
                                    description = "标准的刷新令牌请求格式",
                                    value = """
                                            {
                                              "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJqb2huX3NtaXRoIiwiaWF0IjoxNjE2MjM5MDIyLCJleHAiOjE2MTYzMjU0MjJ9.8HwFUiTKVG8K9YfauUt2-TbHcvn0x1z8Xss4qgpUOkz"
                                            }
                                            """
                            )
                    )
            )
            @RequestBody Map<String, String> request
    ) {
        try {
            String refreshToken = request.get("refreshToken");
            String newAccessToken = userService.refreshToken(refreshToken);
            return ResponseEntity.ok(new JwtResponse(newAccessToken, refreshToken, null, null));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}